package de.tub.pong.objects;

import java.util.List;

import processing.core.PApplet;
import de.tub.pong.main.Pong;

public class Ball {

	// statics
	private static final float ballHeight = 20;

	// variable
	private float velocity; // pixel per frame
	private int timer;
	private float defaultVelocity = 7;
	private float x = 20;
	private float y = 450;

	private static int dX = 1; // 1 => moving right; -1 => moving left
	private static int dY = 1; // 1=> moving down; -1 => moving up

	private PApplet parent;

	public Ball(PApplet parent) {
		this.parent = parent;
		this.velocity = this.defaultVelocity;
		this.timer = parent.millis();
	}

	public float getLeftX() {
		return x;
	}

	public float getRightX() {
		return x + ballHeight;
	}

	/**
	 * Gives the x value in dependence to moving direction
	 * 
	 * @return leftX in case ball is moving in left direction, otherwise rightX
	 */
	public float getFrontEdgeX() {
		return dX == 1 ? getRightX() : getLeftX();
	}

	public float getUpperY() {
		return y;
	}

	public float getLowerY() {
		return y + ballHeight;
	}

	public int getdX() {
		return dX;
	}

	public static void setdX(int dX) {
		Ball.dX = dX;
	}

	public int getdY() {
		return dY;
	}

	public static void setdY(int dY) {
		Ball.dY = dY;
	}

	public float getVelocity() {
		return this.velocity;
	}

	public void raiseVelocity() {
		this.velocity++;
	}

	public void reduceVelocity() {
		this.velocity--;
	}

	public void simulate(float simRange, List<Racket> rackets) {

		// simulate
		x += simRange * dX;
		y += simRange * dY;

		// change directions if necessary
		// lower border
		if (this.getLowerY() >= parent.height) {
			dY = -1;
		}
		// upper border
		else if (this.getUpperY() <= 0) {
			dY = 1;
		}

		for (Racket r : rackets) {

			// left racket collision
			if (this.getLeftX() == r.getRightX()) {
				if (this.getLowerY() > r.getUpperY()
						&& this.getUpperY() < r.getLowerY()) {
					dX = 1;
				}
			}
			// right racket collision
			else if (this.getRightX() == r.getLeftX()) {
				if (this.getLowerY() > r.getUpperY()
						&& this.getUpperY() < r.getLowerY()) {
					dX = -1;
				}
			}
		}

		// reset ball on other site
		if (this.getLeftX() > parent.width) {
			this.x = 0;
			((Pong) parent).raiseScore(1);
			// predictionBuffer = -1;
			timer = parent.millis();
		} else if (this.getRightX() < 0) {
			this.x = parent.width;
			((Pong) parent).raiseScore(2);
			// predictionBuffer = -1;
			timer = parent.millis();
		}

		velocity = (parent.millis() - timer) / 3000 + defaultVelocity;
	}

	public void draw() {
		parent.rect(x, y, ballHeight, ballHeight);
	}
}
